package com.zxl.launch_app

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.annotation.NonNull

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result

/** LaunchAppPlugin */
class LaunchAppPlugin: FlutterPlugin,  MethodCallHandler , ActivityAware{

  private lateinit var channel : MethodChannel
  private var application : Context? =null
  private var activity : Activity? =null

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "com.zxl/launch_app")
    channel.setMethodCallHandler(this)
    application=flutterPluginBinding.applicationContext
  }


  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)
    application=null
  }

  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    val arguments=call.argument<Any>("arguments") as Map<String, *>?

    val packageName = call.argument<String>("package")
    val bundle = convertArguments(arguments)
    if ("launch".equals(call.method, ignoreCase = true)) {
      activity?.run {
        if (packageName!=null){
          val intent= packageManager.getLaunchIntentForPackage(packageName)
          intent?.run {
            flags= 805306368
            if (bundle != null) {
              putExtras(bundle)
            }
            startActivity(intent)
          }
        }
      }
      result.success(null)
    }else {
      result.notImplemented()
    }
  }

  override fun onAttachedToActivity(bind: ActivityPluginBinding) {
    activity=bind.activity
  }

  override fun onDetachedFromActivityForConfigChanges() {
    activity=null
  }

  override fun onReattachedToActivityForConfigChanges(bind: ActivityPluginBinding) {
    activity=bind.activity
  }

  override fun onDetachedFromActivity() {
    activity=null
  }

  private fun convertArguments(arguments: Map<String, *>?): Bundle? {
    val bundle = Bundle()
    if (arguments == null) {
      Log.w("zxl","----arguments=null-----")
      return bundle
    }
    for (key in arguments.keys) {
      val value = arguments[key]

      if (value is Int) {
        bundle.putInt(key, (value as Int?)!!)
      } else if (value is String) {
        Log.w("zxl","$key=$value")
        bundle.putString(key, value as String?)
      } else if (value is Boolean) {
        bundle.putBoolean(key, (value as Boolean?)!!)
      } else if (value is Double) {
        bundle.putDouble(key, (value as Double?)!!)
      } else if (value is Long) {
        bundle.putLong(key, (value as Long?)!!)
      } else if (value is ByteArray) {
        bundle.putByteArray(key, value as ByteArray?)
      } else if (value is IntArray) {
        bundle.putIntArray(key, value as IntArray?)
      } else if (value is LongArray) {
        bundle.putLongArray(key, value as LongArray?)
      } else if (value is DoubleArray) {
        bundle.putDoubleArray(key, value as DoubleArray?)
      } else if (isTypedArrayList(value, Int::class.java)
      ) {
        bundle.putIntegerArrayList(key, value as ArrayList<Int?>?)
      } else if (isTypedArrayList(value, String::class.java)
      ) {
        bundle.putStringArrayList(key, value as ArrayList<String?>?)
      } else if (isStringKeyedMap(value)) {
        bundle.putBundle(key, convertArguments(value as Map<String, *>?))
      } else {
        throw UnsupportedOperationException("Unsupported type $value")
      }
    }
    return bundle
  }
  private fun isTypedArrayList(value: Any?, type: Class<*>): Boolean {
    if (value !is ArrayList<*>) {
      return false
    }
    for (o in value) {
      if (!(o == null || type.isInstance(o))) {
        return false
      }
    }
    return true
  }

  private fun isStringKeyedMap(value: Any?): Boolean {
    if (value !is Map<*, *>) {
      return false
    }
    for (key in value.keys) {
      if (!(key == null || key is String)) {
        return false
      }
    }
    return true
  }
}
